const SHEET_NAME = "Log";
const LABEL_DERIVADO = "IA/Derivado";
const LABEL_REVISAR = "IA/Revisar";
const SEARCH_QUERY = 'in:inbox -label:"IA/Derivado" -label:"IA/Revisar" newer_than:7d';
const MAX_THREADS = 20;

const DESTINOS = {
  "Obras": "obras@ethosia.com.ar",
  "Servicios Públicos": "serviciospublicos@ethosia.com.ar",
  "Tránsito": "transito@ethosia.com.ar",
  "Habilitaciones": "habilitaciones@ethosia.com.ar",
  "Desarrollo Social": "desarrollosocial@ethosia.com.ar",
  "Salud": "salud@ethosia.com.ar",
  "Atención al Vecino": "atencionalvecino@ethosia.com.ar",
  "Otros": "atencionalvecino@ethosia.com.ar"
};

function procesarInbox() {
  const sheet = getOrCreateLogSheet_(SHEET_NAME);
  ensureLogHeader_(sheet);

  const labelDerivado = getOrCreateLabel_(LABEL_DERIVADO);
  const labelRevisar = getOrCreateLabel_(LABEL_REVISAR);

  const threads = GmailApp.search(SEARCH_QUERY, 0, MAX_THREADS);

  threads.forEach(thread => {
    try {
      const msg = getLastMessage_(thread);
      const subject = msg.getSubject() || "";
      const body = sanitizeBody_(msg.getPlainBody() || "");
      const from = msg.getFrom() || "";
      const messageId = msg.getId();

      const clasif = clasificarConIA(subject, body);

      const tema = (clasif && clasif.tema) ? clasif.tema : "Otros";
      const destino = DESTINOS[tema] || DESTINOS["Otros"];
      const resumen = (clasif && clasif.resumen_1_linea) ? String(clasif.resumen_1_linea) : "";
      const confianza = (clasif && clasif.confianza) ? String(clasif.confianza) : "";

      GmailApp.sendEmail(
        destino,
        "[Derivado] " + subject,
        "Resumen: " + resumen + "\n\n---\nCorreo original:\n" + body
      );

      const respuestaVecino = redactarRespuestaVecinoIA_(tema, resumen, (clasif && clasif.urgencia) ? clasif.urgencia : "Media", subject, body);
      responderAlVecino_(msg, respuestaVecino);

      thread.addLabel(labelDerivado);

      sheet.appendRow([
        new Date(),
        messageId,
        from,
        subject,
        tema,
        (clasif && clasif.subtema) ? clasif.subtema : "",
        (clasif && clasif.intencion) ? clasif.intencion : "",
        (clasif && clasif.urgencia) ? clasif.urgencia : "",
        destino,
        resumen,
        confianza,
        "Derivado",
        "Sí",
        ""
      ]);
    } catch (e) {
      try {
        thread.addLabel(labelRevisar);
      } catch (_) {}

      const errMsg = (e && e.message) ? e.message : String(e);

      try {
        const msg = getLastMessage_(thread);
        sheet.appendRow([
          new Date(),
          msg.getId(),
          msg.getFrom() || "",
          msg.getSubject() || "",
          "",
          "",
          "",
          "",
          "",
          "",
          "",
          "Revisar",
          "No",
          errMsg
        ]);
      } catch (_) {
        sheet.appendRow([
          new Date(),
          "",
          "",
          "",
          "",
          "",
          "",
          "",
          "",
          "",
          "",
          "Revisar",
          "No",
          errMsg
        ]);
      }
    }
  });
}

function clasificarConIA(subject, body) {
  const apiKey = PropertiesService.getScriptProperties().getProperty("OPENAI_API_KEY");
  if (!apiKey) throw new Error("Falta OPENAI_API_KEY en Script Properties");

  const prompt = promptClasificacionEmail_(subject, body);

  const schema = {
    type: "object",
    additionalProperties: false,
    required: ["tema", "subtema", "intencion", "urgencia", "resumen_1_linea", "confianza"],
    properties: {
      tema: {
        type: "string",
        enum: ["Obras", "Servicios Públicos", "Tránsito", "Habilitaciones", "Desarrollo Social", "Salud", "Atención al Vecino", "Otros"]
      },
      subtema: { type: "string" },
      intencion: { type: "string", enum: ["Reclamo", "Consulta", "Denuncia", "Turno", "Sugerencia", "Otro"] },
      urgencia: { type: "string", enum: ["Alta", "Media", "Baja"] },
      resumen_1_linea: { type: "string" },
      confianza: { type: "string", enum: ["alta", "media", "baja"] }
    }
  };

  const payload = {
    model: "gpt-4.1-mini",
    store: false,
    input: [
      { role: "system", content: "Clasificás emails municipales y devolvés salida que cumpla el esquema." },
      { role: "user", content: prompt }
    ],
    text: {
      format: {
        type: "json_schema",
        name: "email_classification",
        schema: schema,
        strict: true
      }
    }
  };

  const res = UrlFetchApp.fetch("https://api.openai.com/v1/responses", {
    method: "post",
    contentType: "application/json",
    headers: { Authorization: "Bearer " + apiKey },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  });

  const status = res.getResponseCode();
  const raw = res.getContentText();

  if (status < 200 || status >= 300) throw new Error("OpenAI error " + status + ": " + raw);

  const json = JSON.parse(raw);
  const text = extractOutputText_(json);
  return JSON.parse(text);
}

function redactarRespuestaVecinoIA_(tema, resumen, urgencia, subject, body) {
  const apiKey = PropertiesService.getScriptProperties().getProperty("OPENAI_API_KEY");
  if (!apiKey) throw new Error("Falta OPENAI_API_KEY en Script Properties");

  const datoFaltanteSugerido = datoFaltantePorTema_(tema, subject, body);

  const schema = {
    type: "object",
    additionalProperties: false,
    required: ["respuesta"],
    properties: {
      respuesta: { type: "string" }
    }
  };

  const prompt = [
    "Redactá una respuesta breve y respetuosa para el vecino.",
    "Máximo 70 palabras.",
    "Debe confirmar recepción, indicar el área a la que se derivó, sugerir un plazo tentativo genérico sin prometer fechas.",
    "Si hace falta, pedí un solo dato faltante.",
    "No uses saludos extensos ni firmas largas.",
    "",
    "Datos",
    "tema=" + tema,
    "resumen=" + resumen,
    "urgencia=" + urgencia,
    "dato_faltante_sugerido=" + (datoFaltanteSugerido || "ninguno"),
    "",
    "Asunto original",
    subject,
    "",
    "Cuerpo original",
    body
  ].join("\n");

  const payload = {
    model: "gpt-4.1-mini",
    store: false,
    input: [
      { role: "system", content: "Respondés como mesa de entradas municipal. Tono institucional, claro y breve." },
      { role: "user", content: prompt }
    ],
    text: {
      format: {
        type: "json_schema",
        name: "respuesta_vecino",
        schema: schema,
        strict: true
      }
    }
  };

  const res = UrlFetchApp.fetch("https://api.openai.com/v1/responses", {
    method: "post",
    contentType: "application/json",
    headers: { Authorization: "Bearer " + apiKey },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  });

  const status = res.getResponseCode();
  const raw = res.getContentText();

  if (status < 200 || status >= 300) throw new Error("OpenAI error " + status + ": " + raw);

  const json = JSON.parse(raw);
  const text = extractOutputText_(json);
  const obj = JSON.parse(text);

  const respuesta = (obj && obj.respuesta) ? String(obj.respuesta).trim() : "";
  if (!respuesta) throw new Error("La IA no devolvió respuesta");

  const words = respuesta.split(/\s+/).filter(Boolean).length;
  if (words > 70) return recortarA70Palabras_(respuesta);

  return respuesta;
}

function responderAlVecino_(msg, respuesta) {
  const to = (msg.getFrom() || "").toLowerCase();
  if (!respuesta) return;
  if (to.indexOf("no-reply") !== -1) return;
  if (to.indexOf("noreply") !== -1) return;

  msg.reply(respuesta, { subject: "Re: " + (msg.getSubject() || "") });
}

function promptClasificacionEmail_(subject, body) {
  return [
    "Clasificá este email y generá resumen.",
    "ASUNTO: " + subject,
    "CUERPO: " + body
  ].join("\n");
}

function datoFaltantePorTema_(tema, subject, body) {
  const text = (subject + "\n" + body).toLowerCase();

  if (tema === "Obras") {
    if (!tieneDireccion_(text)) return "dirección exacta y altura del lugar";
    return "";
  }

  if (tema === "Servicios Públicos") {
    if (!tieneDireccion_(text)) return "dirección exacta y referencia del lugar";
    return "";
  }

  if (tema === "Tránsito") {
    const tieneCruce = /(esquina|intersecci|cruce)/.test(text) || tieneDireccion_(text);
    const tienePatente = /\b[a-z]{2}\s?\d{3}\s?[a-z]{2}\b|\b[a-z]{3}\s?\d{3}\b/.test(text);
    if (!tieneCruce) return "ubicación precisa (calle y altura o intersección)";
    if (!tienePatente && /(auto|veh[ií]culo|moto|patente)/.test(text)) return "patente del vehículo, si corresponde";
    return "";
  }

  if (tema === "Habilitaciones") {
    const tieneCuit = /\b\d{2}-\d{8}-\d\b|\b\d{11}\b/.test(text);
    if (!tieneCuit) return "CUIT o razón social";
    if (!tieneDireccion_(text)) return "domicilio del comercio o actividad";
    return "";
  }

  if (tema === "Desarrollo Social") {
    const tieneDni = /\b\d{7,8}\b/.test(text);
    if (!tieneDni) return "DNI y un teléfono de contacto";
    return "";
  }

  if (tema === "Salud") {
    const tieneDni = /\b\d{7,8}\b/.test(text);
    if (!tieneDni) return "DNI y centro de salud de referencia, si corresponde";
    return "";
  }

  if (tema === "Atención al Vecino" || tema === "Otros") {
    if (!tieneDireccion_(text)) return "dirección o ubicación del hecho";
    return "";
  }

  return "";
}

function tieneDireccion_(text) {
  if (/(calle|av\.|avenida|ruta|km|altura|n[úu]mero)/.test(text)) return true;
  if (/\b\d{1,5}\b/.test(text) && /(calle|av|avenida)/.test(text)) return true;
  return false;
}

function recortarA70Palabras_(t) {
  const words = String(t).trim().split(/\s+/).filter(Boolean);
  return words.slice(0, 70).join(" ").replace(/\s+([.,;:!?])/g, "$1");
}

function extractOutputText_(respJson) {
  const output = (respJson && respJson.output) ? respJson.output : [];
  for (var i = 0; i < output.length; i++) {
    const item = output[i];
    if (item && item.type === "message" && item.content && item.content.length) {
      for (var j = 0; j < item.content.length; j++) {
        const c = item.content[j];
        if (c && (c.type === "output_text" || c.type === "text") && c.text) return c.text;
      }
    }
  }
  throw new Error("No se encontró output_text en la respuesta");
}

function getOrCreateLabel_(name) {
  return GmailApp.getUserLabelByName(name) || GmailApp.createLabel(name);
}

function getOrCreateLogSheet_(sheetName) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = ss.getSheetByName(sheetName);
  if (!sheet) sheet = ss.insertSheet(sheetName);
  return sheet;
}

function ensureLogHeader_(sheet) {
  const header = [
    "Fecha",
    "MessageId",
    "From",
    "Subject",
    "Tema",
    "Subtema",
    "Intencion",
    "Urgencia",
    "Destino",
    "Resumen",
    "Confianza",
    "Estado",
    "Respondido",
    "Error"
  ];

  const lastRow = sheet.getLastRow();
  if (lastRow === 0) {
    sheet.getRange(1, 1, 1, header.length).setValues([header]);
    return;
  }

  const firstRow = sheet.getRange(1, 1, 1, header.length).getValues()[0];
  const isHeaderMissing = firstRow.join("").trim() === "";
  if (isHeaderMissing) sheet.getRange(1, 1, 1, header.length).setValues([header]);
}

function getLastMessage_(thread) {
  const msgs = thread.getMessages();
  return msgs[msgs.length - 1];
}

function sanitizeBody_(text) {
  const cleaned = String(text)
    .replace(/\r\n/g, "\n")
    .replace(/\n{3,}/g, "\n\n")
    .trim();

  return cleaned.slice(0, 6000);
}